using System;
using System.Security.Principal;

namespace InfiniTec.DirectoryServices
{
    /// <summary>
    /// Extends the <see cref="ActiveDirectoryPrincipal"/> class with properties
    /// unique to ActiveDirectory users.
    /// </summary>
    public class ActiveDirectoryUser : ActiveDirectoryContact
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ActiveDirectoryUser"/> class.
        /// </summary>
        /// <param name="objectId">The object id.</param>
        /// <param name="connection">The connection.</param>
        public ActiveDirectoryUser(Guid objectId, Connection connection) : base(objectId, connection)
        {
            RequiredFields.Add(WellknownProperties.GroupMembership.TokenGroups);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ActiveDirectoryUser"/> class.
        /// </summary>
        /// <param name="name">The name of the element. This can be a distinguished name, nt4 account name, email address, legacy exchange distinguished name or a display name. In the latter case, Ambiguous name resolution is used to find the principal.</param>
        /// <param name="connection">The connection.</param>
        /// <remarks>
        /// This constructor is equivalent to the constructor <see cref="ActiveDirectoryPrincipal(string, NameHint, Connection)"/>.
        /// </remarks>
        public ActiveDirectoryUser(string name, Connection connection) : base(name, connection)
        {
            RequiredFields.Add(WellknownProperties.GroupMembership.TokenGroups);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ActiveDirectoryUser"/> class.
        /// </summary>
        /// <param name="identifier">The identifier.</param>
        /// <param name="connection">The connection.</param>
        public ActiveDirectoryUser(SecurityIdentifier identifier, Connection connection) : base(identifier, connection)
        {
            RequiredFields.Add(WellknownProperties.GroupMembership.TokenGroups);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ActiveDirectoryUser"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="hint">The hint.</param>
        /// <param name="connection">The connection.</param>
        public ActiveDirectoryUser(string name, NameHint hint, Connection connection) : base(name, hint, connection)
        {
            RequiredFields.Add(WellknownProperties.GroupMembership.TokenGroups);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ActiveDirectoryUser"/> class.
        /// </summary>
        /// <param name="baseItem">The base item.</param>
        public ActiveDirectoryUser(Item baseItem) : base(baseItem)
        {
            RequiredFields.Add(WellknownProperties.GroupMembership.TokenGroups);
        }

        /// <summary>
        /// Gets or sets the manager.
        /// </summary>
        /// <value>The manager.</value>
        public string Manager
        {
            get { return Properties.GetPropertyValue(WellknownProperties.User.Manager); }
            set { Properties.SetPropertyValue(WellknownProperties.User.Manager, value); }
        }

        /// <summary>
        /// Gets the resolve types.
        /// </summary>
        /// <returns></returns>
        protected override ResolveTypes GetResolveTypes()
        {
            return ResolveTypes.User;
        }

        /// <summary>
        /// Gets an <see cref="ActiveDirectoryUser" /> instance for the currently logged on user.
        /// </summary>
        /// <param name="connection">The connection to use.</param>
        /// <returns> an <see cref="ActiveDirectoryUser" /> instance for the currently logged on user. </returns>
        public static ActiveDirectoryUser GetCurrent(Connection connection)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }
            return new ActiveDirectoryUser(WindowsIdentity.GetCurrent().User, connection);
        }

        /// <summary>
        /// Gets the item of the manager of the current user.
        /// </summary>
        /// <returns></returns>
        public ActiveDirectoryUser GetManagerItem()
        {
            if (string.IsNullOrEmpty(Manager)) throw new ManagerNotSpecifiedException("No manager has been specified on item " + DistinguishedName);

            return new ActiveDirectoryUser(Manager, BaseItem.Connection);
        }
    }
}